home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
pascal
/
gr_col.exe
/
GR_READ.ME
< prev
next >
Wrap
Text File
|
1993-04-17
|
9KB
|
168 lines
USING WRITELN WHILE IN GRAPHICS
For some time I have been intrigued with the idea of using standard text
output routines like write, writeln, gotoXY, textcolor, etc. while in 640 X
480 VGA graphics. Why would anyone want to do that? Well, for one thing, it's
easier! Horse puckey, you say: what's the matter with Outtext and OuttextXY?
For starters, I have to convert everything to a string. For another, the
functions are not as flexible as writeln, since I can only output one string
at a time. For a third reason, the default system font is ugly and the stroke
fonts use more memory and are slow.
Conventional wisdom (i.e., that taught by the "experts") says that you really
can't use write/writeln and read/readln effectively while in graphics. All the
books go to great lengths to develop elaborate routines for doing keyboard
input and graphics text output when plain old readln and writeln work just
fine.
But, I hear you say, you can't text control position precisely and you can't
control color well at all when using text I/O. And, you have to remember to
turn DirectVideo off. As it turns out, these are real limitations, but they
can be gotten around. Almost. I still use Outtext when I want its power but I
use writeln for ease and speed.
The programs I'm about to describe alleviate many of the limitations of
graphics use of text I/O, namely color control and blinking text.
First, some background.
As is well known (I think), IBM text video architecture controls screen
appearance with "attribute" bytes for each character of text on screen. Of the
8 bits, the lower 4 bits are for the text foreground color (4 bits = 16
possible colors). The next 3 bits define background color (3 bits = 8 colors),
which is why you ordinarily can't get the high intensity colors (like
LightCyan) for backgrounds. The high order bit is normally used to set
blinking text.
However, a BIOS int 10h sub-function 10h can, among other things, change the
way the blink bit is interpreted. In pure text mode, the blink bit (bit 7 of
the attribute byte) can be used to select blinking and normal text, or it can
be used to select high intensity or normal backgrounds. So, you CAN have the
high intensity backgrounds. A simple assembly fragment can do this:
PROCEDURE HiBit; assembler;
asm
MOV AX, 1003H
MOV BL, Blink
INT 10H
end;
If Blink in the above routine is set to "1", bit 7 will select blinking text.
If Blink is set to "0", then high intensity backgrounds can be used.
All that remains is to make sure that bit 7 of the attribute byte is set.
This can be done one of two ways:
TextAttr := TextAttr or $80
TextColor( Color + 128 ); { color can be 0 to 15 }
Note that to "clear" bit 7 you can do one of these two things:
TextAttr := TextAttr and $7F
TextColor( Color ); { color can be 0 to 15 }
Now for the fun part: in graphics the BIOS uses bit 7 of the same attribute
byte to control how text is written to the graphics screen! If bit 7 = 0 (the
normal case), text is written with the desired foreground color (TextColor
again) and the default background color, normally black. This is why write-ing
text onto graphics looks dumb: the background of all the characters wipes out
your pretty graphics picture.
But, if bit 7 = 1, then the BIOS XOR's the text over the top of the existing
graphic! Wow! think of the possibilities! For one, its now super easy to erase
a line of text. No more tedious overwrites with "background" color or weird
schemes like using Bar or Bar3D to "erase" the text. Now, all you have to do
is re-write the text and voila, it disappears! Or, more correctly, anything
XOR'd onto itself restores the image to what it was before anything was drawn
(this is the theory behind the XORmode of graphics).
Ah, but there's a problem (isn't there always?). When you XOR text onto a
graphic, the colors come out all wonky. Again, more correctly, the text color
becomes the inverse of what you thought it'd be because of XOR swapping all
the color bits around.
If only you could figure out in advance what the inverse of a given text color
against a given background color is, you could supply that to TextColor and
your text would XOR back to the original "desired" color.
Well, now you can! With the help of a utility procedure I hacked together
(XorColConv in the GR_COL2G.PAS and GR_DEMO1.PAS files).
Briefly, what the XorColConv procedure does is this: it XORs the bits for
background (graphic) color and foreground (text) color to get an inverse
color. Then, this "color" is compared to the 16 standard VGA colors for a
match. 2/3 of the times you try this, you'll get a match. The rest of the
time, the resulting "color" is a legal VGA value, but not one of the colors in
the standard 16-color palette.
Remembering that the Red/Green/Blue (RGB) values for a VGA color can each have
64 values (0 to 63), you could have up to 64 * 64 * 64 = 262,144 possible
colors, of which any 16 can be used at a time. You did remember that, didn't
you? Well, it turns out that out of all possible combinations of "standard"
background and foreground colors, there are only 29 "exception" RGB values.
This can easily be put into a lookup table, which is what I did.
I have to confess, though, that this all wasn't obvious to me when I started
out to write XorColConv. By trial and error, I discovered what was going on
and developed a first-cut look-up table. Then by looking at the resulting
colors visually, I adjusted the exception table to have an acceptable color
mapping when the XOR business didn't come out right.
To make things easy for myself, I converted the RGB values into a single
longint value so that the XOR business was easier and the look-up table was
simpler to construct. Essentially, I combined the RGB values into one integer
like this:
Using LightBlue as an example, Red = $15, Green = $15, Blue = $3F. This gives
a combined value of $15153F = 1381695 decimal. Similarly, I calculated the
other 14 colors (black is 0 in any language).
The exception colors were found by printing diagnostics in my procedure.
Whew! What good is all this stuff?
If you hand XorColConv the background and foreground color you want, it gives
you the XOR color back. Then, you set TextColor + 128 and you're done. All
this is described in excruciating detail in the accompanying demo programs.
The first, GR_COL2G.PAS, is a demo of how each of the 16 VGA colors looks when
XOR'd on each of the 16 color backgrounds. It also outputs text files of all
the stuff I've been talking about above. This ain't too useful unless you,
too, are trying to understand all this gibberish.
The second program, GR_DEMO1.PAS, is a simple demonstration of how these
techniques can be used. It simply writes some text to the screen, erases it
one character at a time, then re-writes again. Finally, it shows how blinking
text can be simulated in graphics.
Whoa! Blinking text? I bet you thought that was impossible or at least a pain
in the butt. Well, it ain't really blinking text, but it is a good simulation
once you imagine blinking as nothing more than write-erase-write-erase, etc.
for as long as you want it to blink.
Finally, there's a simple utility program, RECOL3.PAS which was used to
construct the exception color look-up table from the data provided by
GR_COL2G.PAS.
There's also a few Turbo Pascal limitations (at least, I haven't figured out a
work-around yet!). One is that TP's implementation of write/writeln isn't
standard BIOS stuff. It takes advantage of the fact that a character is
normally 14 pixels high, plus a couple for inter-line spacing. This turns out
to use only 400 of the available 480 pixels on a VGA graphics screen(16 pixels
* 25 lines = 400). So its not quite 80 X 25 VGA text (normal 25 lines would be
480 / 25 = 19.2 pixels high ). Second, changing text styles (40 characters or
50 lines) just don't work.
Anyway, I hope you